/* 
 * jQuery - Collapser - Plugin v1.0
 * http://www.aakashweb.com/
 * Copyright 2010, Aakash Chakravarthy
 * Released under the MIT License.
 */

(function($) {
    $.fn.collapser = function(options, beforeCallback, afterCallback) {

        var defaults = {
            target: 'next',
            targetOnly: null,
            effect: 'slide',
            changeText: true,
            expandHtml: 'Expand',
            collapseHtml: 'Collapse',
            expandClass: '',
            collapseClass: ''
        };

        var options = $.extend(defaults, options);

        var expHtml, collHtml, effectShow, effectHide;

        if (options.effect == 'slide') {
            effectShow = 'slideDown';
            effectHide = 'slideUp';
        } else {
            effectShow = 'fadeIn';
            effectHide = 'fadeOut';
        }

        if (options.changeText == true) {
            expHtml = options.expandHtml;
            collHtml = options.collapseHtml;
        }

        function callBeforeCallback(obj) {
            if (beforeCallback !== undefined) {
                beforeCallback.apply(obj);
            }
        }

        function callAfterCallback(obj) {
            if (afterCallback !== undefined) {
                afterCallback.apply(obj);
            }
        }

        function hideElement(obj, method) {
            callBeforeCallback(obj);
            if (method == 1) {
                obj[options.target](options.targetOnly)[effectHide]();
                obj.html(expHtml);
                obj.removeClass(options.collapseClass);
                obj.addClass(options.expandClass);
            } else {
                $(document).find(options.target)[effectHide]();
                obj.html(expHtml);
                obj.removeClass(options.collapseClass);
                obj.addClass(options.expandClass);
            }
            callAfterCallback(obj);
        }

        function showElement(obj, method) {
            callBeforeCallback(obj);
            if (method == 1) {
                obj[options.target](options.targetOnly)[effectShow]();
                obj.html(collHtml);
                obj.removeClass(options.expandClass);
                obj.addClass(options.collapseClass);
            } else {
                $(document).find(options.target)[effectShow]();
                obj.html(collHtml);
                obj.removeClass(options.expandClass);
                obj.addClass(options.collapseClass);
            }
            callAfterCallback(obj);
        }

        function toggleElement(obj, method) {
            if (method == 1) {
                if (obj[options.target](options.targetOnly).is(':visible')) {
                    hideElement(obj, 1);
                } else {
                    showElement(obj, 1);
                }
            } else {
                if ($(document).find(options.target).is(':visible')) {
                    hideElement(obj, 2);
                } else {
                    showElement(obj, 2);
                }
            }
        }

        return this.each(function() {

            if ($.fn[options.target] && $(this)[options.target]()) {
                $(this).toggle(function() {
                    toggleElement($(this), 1);
                }, function() {
                    toggleElement($(this), 1);
                });

            } else {

                $(this).toggle(function() {
                    toggleElement($(this), 2);
                }, function() {
                    toggleElement($(this), 2);
                });
            }

            // Initialize  
            if ($.fn[options.target] && $(this)[options.target]()) {
                if ($(this)[options.target]().is(':hidden')) {
                    $(this).html(expHtml);
                    $(this).removeClass(options.collapseClass);
                    $(this).addClass(options.expandClass);
                } else {
                    $(this).html(collHtml);
                    $(this).removeClass(options.expandClass);
                    $(this).addClass(options.collapseClass);
                }
            } else {
                if ($(document).find(options.target).is(':hidden')) {
                    $(this).html(expHtml);
                } else {
                    $(this).html(collHtml);
                }
            }

        });
    };

})(jQuery);